/*
* Copyright 2009 NOR_/D Labs <http://labs.nortd.com>
*
* This file is part of SceneExpression.
* SceneExpression is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License 
* as published by the Free Software Foundation, either version 3 of 
* the License, or (at your option) any later version. For details
* see <http://www.gnu.org/licenses/>.
*
* * *
* 
*/

#ifndef SX_EVENTS
#define SX_EVENTS


namespace sx {

class Widget;
class Scene;


class Touch {
    public:
        int id;
        //int initialOrder;
        Widget*   widget;
        Scene*    scene;
        long tapCount;
        double timestamp;
        int phase;
        bool bMouse;
                
        
        Touch() {
            widget = NULL;
            scene = NULL;
            bMouse = false;    
        }
        Touch( float x, float y, int touchId ) {
            id = touchId;
            widget = NULL;
            scene = NULL;
            _screenPosition.set(x,y);
            bMouse = false;
        }
        
        int getId() {
            return id;
        }
        
        void setScreenPosition( float x, float y ) {
            _screenPosition.set(x,y);
        }
        osg::Vec2& getScreenPosition() {
            return _screenPosition;
        }
        float getScreenX() {
            return _screenPosition[0];
        }
        float getScreenY() {
            return _screenPosition[1];
        }

        void setLocalPosition( const osg::Vec3d&  pos ) {
            _localPosition.set(pos);
        }
        osg::Vec3& getLocalPosition() {
            return _localPosition;
        }
                            
        //virtual osg::Vec3 getLocationInView() { return globalLocation; }
        //virtual osg::Vec3 getPreviousLocationInView() {}

   
    protected:
        osg::Vec2 _screenPosition;
        osg::Vec3 _localPosition;
};


class TouchHit {
    // this is used as a temp storage container in
    // the ray intersection routine
    public:
        Widget*   widget;
        osg::Vec2 screenPosition;
        osg::Vec3 localPosition;
        osg::Vec3 worldPosition;
        
        TouchHit( Widget* _widget, 
                    osg::Vec2 _screenPosition,
                    osg::Vec3 _localPosition,
                    osg::Vec3 _worldPosition) :
            widget (_widget),
            screenPosition (_screenPosition),
            localPosition (_localPosition),
            worldPosition (_worldPosition) {}
};



class Key {
    public:    
                
        Key() {
            _key = 0;
        }
        
        int getKey() { return _key; }
        void setKey( int key ) { _key = key; } 
                
    protected:
        int _key;
};


class Mouse {
    public:
            
        Mouse() {
            _x = _y = _scrollingDeltaX = _scrollingDeltaY = 0.0f;
            _button = 0;
        }
        
        float getX() { return _x; }
        void setX( float x ) { _x = x; }
        
        float getY() { return _y; }
        void setY( float y ) { _y = y; }
          
        int getButton() { return _button; }
        void setButton( int button ) { _button = button; }
        
        float getScrollingDeltaX() { return _scrollingDeltaX; }
        float getScrollingDeltaY() { return _scrollingDeltaY; }
        void setScrollingMotionDelta( float dx, float dy ) {
            _scrollingDeltaX = dx;
            _scrollingDeltaY = dy;
        }   

    protected:
        float _x;
        float _y;
        int _button;    
        float _scrollingDeltaX;
        float _scrollingDeltaY;
};


class Pen {
    public:    
        enum TabletPointerType {
            UNKNOWN = 0,
            PEN,
            PUCK,
            ERASER
        };
                
        Pen() {
            _x = _y = 0.0f;
            _pressure = _tiltX = _tiltY = _rotation = 0.0f;
        }
        
        float getX() { return _x; }
        void setX( float x ) { _x = x; }
        float getY() { return _y; }
        void setY( float y ) { _y = y; }        
        /// get the pressure, from a tablet input device (range 0 - 1)
        float getPressure()  const { return _pressure; }
        /// sets the pressure from a tablet
        void setPressure(float pressure) { _pressure = pressure; }
        /// get the tiltX, from a tablet input device (range -1 - 1)
        float getTiltX()  const { return _tiltX; }
        /// sets the tiltX from a tablet
        void setTiltX(float tiltX) { _tiltX = tiltX; }
        /// get the tiltY, from a tablet input device (range -1 - 1)
        float getTiltY()  const { return _tiltY; }
        /// sets the tiltY from a tablet
        void setTiltY(float tiltY) { _tiltY = tiltY; }
        /// get the rotation, from a tablet input device (range 0 - 2PI)
        float getRotation()  const { return _rotation; }
        /// sets the rotation from a tablet
        void setRotation(float rotation) { _rotation = rotation; }
        /// get the orientation from a tablet input device as a matrix
        const osg::Matrix getOrientation() const {
            float xRad = osg::DegreesToRadians ( getTiltY() );
            float yRad = osg::DegreesToRadians ( getTiltX() );
            float zRad = osg::DegreesToRadians ( getRotation() );
            osg::Matrix xrot = osg::Matrix::rotate ( xRad, osg::Vec3f(1.0f, 0.0f, 0.0f) );
            osg::Matrix yrot = osg::Matrix::rotate ( yRad, osg::Vec3f(0.0f, 0.0f, 1.0f) );
            osg::Matrix zrot = osg::Matrix::rotate ( zRad, osg::Vec3f(0.0f, 1.0f, 0.0f) );
            return ( zrot * yrot * xrot );        
        }
        /// get the current used tablet pointer type
        TabletPointerType getPointerType() const { return _tabletPointerType; }
        /// set the current used tablet pointer type
        void setPointerType(TabletPointerType pt) { _tabletPointerType = pt; }
        
    protected:
        float _x;
        float _y;    
        float _pressure;
        float _tiltX;
        float _tiltY;
        float _rotation;
        TabletPointerType _tabletPointerType;            
};




class KeyHandler {
    public:
        virtual ~KeyHandler() {}
        virtual void keyPress( Key& key ) {}
        virtual void keyRelease( Key& key ) {}
};

class MouseHandler {
    public:
        virtual ~MouseHandler() {}   
        virtual void mousePress( Mouse& key ) {}
        virtual void mouseRelease( Mouse& key ) {}
        virtual void mouseMove( Mouse& key ) {}
        virtual void mouseDrag( Mouse& key ) {}
        virtual void mouseScroll( Mouse& key ) {}
        virtual void mouseDoubleclick( Mouse& key ) {}
};

class TouchHandler {
    public:
        virtual ~TouchHandler() {}   
        virtual void touchDown( Touch& touch ) {}
        virtual void touchUp( Touch& touch ) {}
        virtual void touchMove( Touch& touch ) {}
};

class PenHandler {
    public:
        virtual ~PenHandler() {}   
        virtual void penPressure( Pen& pen ) {}
        virtual void penOrientation( Pen& pen ) {}
        virtual void penEnter( Pen& pen ) {}
        virtual void penLeave( Pen& pen ) {}
};

class ButtonWidget;
class ButtonHandler {
    public:
        virtual ~ButtonHandler() {}    
        virtual void widgetButton( ButtonWidget& button ){}
};

class SliderWidget;
class SliderHandler {
    public:
        virtual ~SliderHandler() {}    
        virtual void widgetSlider( SliderWidget& slider ){}
};

class CheckboxWidget;
class CheckboxHandler {
    public:
        virtual ~CheckboxHandler() {}   
        virtual void widgetCheckbox( CheckboxWidget& checkbox ){}
};


}
#endif

